<?php
// +----------------------------------------------------------------------
// | INPHP
// +----------------------------------------------------------------------
// | Copyright (c) 2021 https://inphp.cc All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/MIT )
// +----------------------------------------------------------------------
// | Author: lulanyin <me@lanyin.lu>
// +----------------------------------------------------------------------
// |
// |                          redis 缓存
// |
// +----------------------------------------------------------------------
namespace Inphp\Redis;

use Inphp\App;
use Swoole\Coroutine\Channel;

class Connection
{
    /**
     * 连接池数量
     * @var int
     */
    private int $length = 5;

    /**
     * @var Channel
     */
    private Channel $channels;

    private array $config = [
        'host'       => '127.0.0.1',
        'port'       => 6379,
        'password'   => '',
        'select'     => 0,
        'timeout'    => 0,
        'expire'     => 0,
        'persistent' => false,
        'prefix'     => '',
    ];

    /**
     * 客户端
     * @var \Redis
     */
    public \Redis $redis;

    /**
     * @param array $config
     * @param int $length
     */
    public function __construct(array $config, int $length = 5)
    {
        $this->length = $length;
        $this->setConfig($config);
        $this->putConnect();
    }

    /**
     * 配置
     * @param array $config
     */
    public function setConfig(array $config)
    {
        //host
        $host = $config['host'] ?? '127.0.0.1';
        //port
        $port = $config['port'] ?? 6379;

        $select = $config['select'] ?? 0;
        $select = is_numeric($select) && $select >= 0 && $select <= 6 ? ceil($select) : 0;

        $timeout = $config['timeout'] ?? 0;
        $timeout = is_numeric($timeout) && $timeout >= 0 ? ceil($timeout) : 0;

        $persistent = $config['persistent'] ?? false;

        $this->config = [
            'host'       => $host,
            'port'       => $port,
            'password'   => $config['password'] ?? '',
            'select'     => $select,
            'timeout'    => $timeout,
            'expire'     => $config['expire'] ?? 0,
            'persistent' => $persistent,
            'prefix'     => $config['prefix'] ?? '',
        ];
    }

    /**
     * 连接池
     */
    public function putConnect()
    {
        if(App::isSwoole())
        {
            $this->channels = new Channel($this->length);
            for($i = 0; $i < $this->length; $i++)
            {
                $redis = $this->connect($this->config['host'], $this->config['port'], $this->config['timeout']);
                if(!empty($this->config['password']))
                {
                    $redis->auth($this->config['password']);
                }
                if(0 != $this->config['select'])
                {
                    $redis->select($this->config['select']);
                }
                $this->put($redis);
            }
        }
        else
        {
            $this->redis = $this->connect($this->config['host'], $this->config['port'], $this->config['timeout']);
            if(!empty($this->config['password']))
            {
                $this->redis->auth($this->config['password']);
            }
            if(0 != $this->config['select'])
            {
                $this->redis->select($this->config['select']);
            }
        }
    }

    /**
     * 回收
     * @param \Redis $redis
     */
    public function put(\Redis $redis)
    {
        $this->channels->push($redis);
    }

    /**
     * 获取
     * @return \Redis|null
     */
    public function get(): \Redis|null
    {
        $redis = $this->channels->pop(2);
        return $redis ?? null;
    }
    
    /**
     * 回收，仅在swoole服务运行下支持
     * @param \Redis $redis
     */
    public function release(\Redis $redis)
    {
        if(App::isSwoole())
        {
            $this->put($redis);
        }
    }

    /**
     * 连接
     * @param string $host
     * @param int $port
     * @param int $timeout
     * @return \Redis|false
     */
    public function connect(string $host = '127.0.0.1', int $port = 6379, int $timeout = 0): \Redis|false
    {
        $redis = new \Redis();
        $redis->connect($host, $port, $timeout);
        return $redis;
    }
}